1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.primitives;
18
19 import static com.google.common.truth.Truth.assertThat;
20 import static java.lang.Double.NaN;
21
22 import com.google.common.annotations.GwtCompatible;
23 import com.google.common.annotations.GwtIncompatible;
24 import com.google.common.base.Converter;
25 import com.google.common.collect.ImmutableList;
26 import com.google.common.collect.testing.Helpers;
27 import com.google.common.testing.NullPointerTester;
28 import com.google.common.testing.SerializableTester;
29
30 import junit.framework.TestCase;
31
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Collections;
35 import java.util.Comparator;
36 import java.util.List;
37
38
39
40
41
42
43 @GwtCompatible(emulated = true)
44 @SuppressWarnings("cast")
45 public class DoublesTest extends TestCase {
46 private static final double[] EMPTY = {};
47 private static final double[] ARRAY1 = {(double) 1};
48 private static final double[] ARRAY234
49 = {(double) 2, (double) 3, (double) 4};
50
51 private static final double LEAST = Double.NEGATIVE_INFINITY;
52 private static final double GREATEST = Double.POSITIVE_INFINITY;
53
54 private static final double[] NUMBERS = new double[] {
55 LEAST, -Double.MAX_VALUE, -1.0, -0.5, -0.1, -0.0, 0.0, 0.1, 0.5, 1.0,
56 Double.MAX_VALUE, GREATEST, Double.MIN_NORMAL, -Double.MIN_NORMAL,
57 Double.MIN_VALUE, -Double.MIN_VALUE, Integer.MIN_VALUE,
58 Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE
59 };
60
61 private static final double[] VALUES
62 = Doubles.concat(NUMBERS, new double[] {NaN});
63
64 public void testHashCode() {
65 for (double value : VALUES) {
66 assertEquals(((Double) value).hashCode(), Doubles.hashCode(value));
67 }
68 }
69
70 public void testIsFinite() {
71 for (double value : NUMBERS) {
72 assertEquals(!(Double.isNaN(value) || Double.isInfinite(value)), Doubles.isFinite(value));
73 }
74 }
75
76 public void testCompare() {
77 for (double x : VALUES) {
78 for (double y : VALUES) {
79
80 assertEquals(x + ", " + y,
81 Double.valueOf(x).compareTo(y),
82 Doubles.compare(x, y));
83 }
84 }
85 }
86
87 public void testContains() {
88 assertFalse(Doubles.contains(EMPTY, (double) 1));
89 assertFalse(Doubles.contains(ARRAY1, (double) 2));
90 assertFalse(Doubles.contains(ARRAY234, (double) 1));
91 assertTrue(Doubles.contains(new double[] {(double) -1}, (double) -1));
92 assertTrue(Doubles.contains(ARRAY234, (double) 2));
93 assertTrue(Doubles.contains(ARRAY234, (double) 3));
94 assertTrue(Doubles.contains(ARRAY234, (double) 4));
95
96 for (double value : NUMBERS) {
97 assertTrue("" + value,
98 Doubles.contains(new double[] {5.0, value}, value));
99 }
100 assertFalse(Doubles.contains(new double[] {5.0, NaN}, NaN));
101 }
102
103 public void testIndexOf() {
104 assertEquals(-1, Doubles.indexOf(EMPTY, (double) 1));
105 assertEquals(-1, Doubles.indexOf(ARRAY1, (double) 2));
106 assertEquals(-1, Doubles.indexOf(ARRAY234, (double) 1));
107 assertEquals(0, Doubles.indexOf(
108 new double[] {(double) -1}, (double) -1));
109 assertEquals(0, Doubles.indexOf(ARRAY234, (double) 2));
110 assertEquals(1, Doubles.indexOf(ARRAY234, (double) 3));
111 assertEquals(2, Doubles.indexOf(ARRAY234, (double) 4));
112 assertEquals(1, Doubles.indexOf(
113 new double[] { (double) 2, (double) 3, (double) 2, (double) 3 },
114 (double) 3));
115
116 for (double value : NUMBERS) {
117 assertEquals("" + value,
118 1, Doubles.indexOf(new double[] {5.0, value}, value));
119 }
120 assertEquals(-1, Doubles.indexOf(new double[] {5.0, NaN}, NaN));
121 }
122
123 public void testIndexOf_arrayTarget() {
124 assertEquals(0, Doubles.indexOf(EMPTY, EMPTY));
125 assertEquals(0, Doubles.indexOf(ARRAY234, EMPTY));
126 assertEquals(-1, Doubles.indexOf(EMPTY, ARRAY234));
127 assertEquals(-1, Doubles.indexOf(ARRAY234, ARRAY1));
128 assertEquals(-1, Doubles.indexOf(ARRAY1, ARRAY234));
129 assertEquals(0, Doubles.indexOf(ARRAY1, ARRAY1));
130 assertEquals(0, Doubles.indexOf(ARRAY234, ARRAY234));
131 assertEquals(0, Doubles.indexOf(
132 ARRAY234, new double[] { (double) 2, (double) 3 }));
133 assertEquals(1, Doubles.indexOf(
134 ARRAY234, new double[] { (double) 3, (double) 4 }));
135 assertEquals(1, Doubles.indexOf(ARRAY234, new double[] { (double) 3 }));
136 assertEquals(2, Doubles.indexOf(ARRAY234, new double[] { (double) 4 }));
137 assertEquals(1, Doubles.indexOf(new double[] { (double) 2, (double) 3,
138 (double) 3, (double) 3, (double) 3 },
139 new double[] { (double) 3 }
140 ));
141 assertEquals(2, Doubles.indexOf(
142 new double[] { (double) 2, (double) 3, (double) 2,
143 (double) 3, (double) 4, (double) 2, (double) 3},
144 new double[] { (double) 2, (double) 3, (double) 4}
145 ));
146 assertEquals(1, Doubles.indexOf(
147 new double[] { (double) 2, (double) 2, (double) 3,
148 (double) 4, (double) 2, (double) 3, (double) 4},
149 new double[] { (double) 2, (double) 3, (double) 4}
150 ));
151 assertEquals(-1, Doubles.indexOf(
152 new double[] { (double) 4, (double) 3, (double) 2},
153 new double[] { (double) 2, (double) 3, (double) 4}
154 ));
155
156 for (double value : NUMBERS) {
157 assertEquals("" + value, 1, Doubles.indexOf(
158 new double[] {5.0, value, value, 5.0}, new double[] {value, value}));
159 }
160 assertEquals(-1, Doubles.indexOf(
161 new double[] {5.0, NaN, NaN, 5.0}, new double[] {NaN, NaN}));
162 }
163
164 public void testLastIndexOf() {
165 assertEquals(-1, Doubles.lastIndexOf(EMPTY, (double) 1));
166 assertEquals(-1, Doubles.lastIndexOf(ARRAY1, (double) 2));
167 assertEquals(-1, Doubles.lastIndexOf(ARRAY234, (double) 1));
168 assertEquals(0, Doubles.lastIndexOf(
169 new double[] {(double) -1}, (double) -1));
170 assertEquals(0, Doubles.lastIndexOf(ARRAY234, (double) 2));
171 assertEquals(1, Doubles.lastIndexOf(ARRAY234, (double) 3));
172 assertEquals(2, Doubles.lastIndexOf(ARRAY234, (double) 4));
173 assertEquals(3, Doubles.lastIndexOf(
174 new double[] { (double) 2, (double) 3, (double) 2, (double) 3 },
175 (double) 3));
176
177 for (double value : NUMBERS) {
178 assertEquals("" + value,
179 0, Doubles.lastIndexOf(new double[] {value, 5.0}, value));
180 }
181 assertEquals(-1, Doubles.lastIndexOf(new double[] {NaN, 5.0}, NaN));
182 }
183
184 public void testMax_noArgs() {
185 try {
186 Doubles.max();
187 fail();
188 } catch (IllegalArgumentException expected) {
189 }
190 }
191
192 public void testMax() {
193 assertEquals(LEAST, Doubles.max(LEAST));
194 assertEquals(GREATEST, Doubles.max(GREATEST));
195 assertEquals((double) 9, Doubles.max(
196 (double) 8, (double) 6, (double) 7,
197 (double) 5, (double) 3, (double) 0, (double) 9));
198
199 assertEquals(0.0, Doubles.max(-0.0, 0.0));
200 assertEquals(0.0, Doubles.max(0.0, -0.0));
201 assertEquals(GREATEST, Doubles.max(NUMBERS));
202 assertTrue(Double.isNaN(Doubles.max(VALUES)));
203 }
204
205 public void testMin_noArgs() {
206 try {
207 Doubles.min();
208 fail();
209 } catch (IllegalArgumentException expected) {
210 }
211 }
212
213 public void testMin() {
214 assertEquals(LEAST, Doubles.min(LEAST));
215 assertEquals(GREATEST, Doubles.min(GREATEST));
216 assertEquals((double) 0, Doubles.min(
217 (double) 8, (double) 6, (double) 7,
218 (double) 5, (double) 3, (double) 0, (double) 9));
219
220 assertEquals(-0.0, Doubles.min(-0.0, 0.0));
221 assertEquals(-0.0, Doubles.min(0.0, -0.0));
222 assertEquals(LEAST, Doubles.min(NUMBERS));
223 assertTrue(Double.isNaN(Doubles.min(VALUES)));
224 }
225
226 public void testConcat() {
227 assertTrue(Arrays.equals(EMPTY, Doubles.concat()));
228 assertTrue(Arrays.equals(EMPTY, Doubles.concat(EMPTY)));
229 assertTrue(Arrays.equals(EMPTY, Doubles.concat(EMPTY, EMPTY, EMPTY)));
230 assertTrue(Arrays.equals(ARRAY1, Doubles.concat(ARRAY1)));
231 assertNotSame(ARRAY1, Doubles.concat(ARRAY1));
232 assertTrue(Arrays.equals(ARRAY1, Doubles.concat(EMPTY, ARRAY1, EMPTY)));
233 assertTrue(Arrays.equals(
234 new double[] {(double) 1, (double) 1, (double) 1},
235 Doubles.concat(ARRAY1, ARRAY1, ARRAY1)));
236 assertTrue(Arrays.equals(
237 new double[] {(double) 1, (double) 2, (double) 3, (double) 4},
238 Doubles.concat(ARRAY1, ARRAY234)));
239 }
240
241 public void testEnsureCapacity() {
242 assertSame(EMPTY, Doubles.ensureCapacity(EMPTY, 0, 1));
243 assertSame(ARRAY1, Doubles.ensureCapacity(ARRAY1, 0, 1));
244 assertSame(ARRAY1, Doubles.ensureCapacity(ARRAY1, 1, 1));
245 assertTrue(Arrays.equals(
246 new double[] {(double) 1, (double) 0, (double) 0},
247 Doubles.ensureCapacity(ARRAY1, 2, 1)));
248 }
249
250 public void testEnsureCapacity_fail() {
251 try {
252 Doubles.ensureCapacity(ARRAY1, -1, 1);
253 fail();
254 } catch (IllegalArgumentException expected) {
255 }
256 try {
257
258 Doubles.ensureCapacity(ARRAY1, 1, -1);
259 fail();
260 } catch (IllegalArgumentException expected) {
261 }
262 }
263
264 @GwtIncompatible("Double.toString returns different value in GWT.")
265 public void testJoin() {
266 assertEquals("", Doubles.join(",", EMPTY));
267 assertEquals("1.0", Doubles.join(",", ARRAY1));
268 assertEquals("1.0,2.0", Doubles.join(",", (double) 1, (double) 2));
269 assertEquals("1.02.03.0",
270 Doubles.join("", (double) 1, (double) 2, (double) 3));
271 }
272
273 public void testJoinNonTrivialDoubles() {
274 assertEquals("", Doubles.join(",", EMPTY));
275 assertEquals("1.2", Doubles.join(",", 1.2));
276 assertEquals("1.3,2.4", Doubles.join(",", 1.3, 2.4));
277 assertEquals("1.42.53.6", Doubles.join("", 1.4, 2.5, 3.6));
278 }
279
280 public void testLexicographicalComparator() {
281 List<double[]> ordered = Arrays.asList(
282 new double[] {},
283 new double[] {LEAST},
284 new double[] {LEAST, LEAST},
285 new double[] {LEAST, (double) 1},
286 new double[] {(double) 1},
287 new double[] {(double) 1, LEAST},
288 new double[] {GREATEST, Double.MAX_VALUE},
289 new double[] {GREATEST, GREATEST},
290 new double[] {GREATEST, GREATEST, GREATEST});
291
292 Comparator<double[]> comparator = Doubles.lexicographicalComparator();
293 Helpers.testComparator(comparator, ordered);
294 }
295
296 @GwtIncompatible("SerializableTester")
297 public void testLexicographicalComparatorSerializable() {
298 Comparator<double[]> comparator = Doubles.lexicographicalComparator();
299 assertSame(comparator, SerializableTester.reserialize(comparator));
300 }
301
302 @GwtIncompatible("SerializableTester")
303 public void testStringConverterSerialization() {
304 SerializableTester.reserializeAndAssert(Doubles.stringConverter());
305 }
306
307 public void testToArray() {
308
309 List<Double> none = Arrays.<Double>asList();
310 assertTrue(Arrays.equals(EMPTY, Doubles.toArray(none)));
311
312 List<Double> one = Arrays.asList((double) 1);
313 assertTrue(Arrays.equals(ARRAY1, Doubles.toArray(one)));
314
315 double[] array = {(double) 0, (double) 1, Math.PI};
316
317 List<Double> three = Arrays.asList((double) 0, (double) 1, Math.PI);
318 assertTrue(Arrays.equals(array, Doubles.toArray(three)));
319
320 assertTrue(Arrays.equals(array, Doubles.toArray(Doubles.asList(array))));
321 }
322
323 public void testToArray_threadSafe() {
324 for (int delta : new int[] { +1, 0, -1 }) {
325 for (int i = 0; i < VALUES.length; i++) {
326 List<Double> list = Doubles.asList(VALUES).subList(0, i);
327 Collection<Double> misleadingSize =
328 Helpers.misleadingSizeCollection(delta);
329 misleadingSize.addAll(list);
330 double[] arr = Doubles.toArray(misleadingSize);
331 assertEquals(i, arr.length);
332 for (int j = 0; j < i; j++) {
333 assertEquals(VALUES[j], arr[j]);
334 }
335 }
336 }
337 }
338
339 public void testToArray_withNull() {
340 List<Double> list = Arrays.asList((double) 0, (double) 1, null);
341 try {
342 Doubles.toArray(list);
343 fail();
344 } catch (NullPointerException expected) {
345 }
346 }
347
348 public void testToArray_withConversion() {
349 double[] array = {(double) 0, (double) 1, (double) 2};
350
351 List<Byte> bytes = Arrays.asList((byte) 0, (byte) 1, (byte) 2);
352 List<Short> shorts = Arrays.asList((short) 0, (short) 1, (short) 2);
353 List<Integer> ints = Arrays.asList(0, 1, 2);
354 List<Float> floats = Arrays.asList((float) 0, (float) 1, (float) 2);
355 List<Long> longs = Arrays.asList((long) 0, (long) 1, (long) 2);
356 List<Double> doubles = Arrays.asList((double) 0, (double) 1, (double) 2);
357
358 assertTrue(Arrays.equals(array, Doubles.toArray(bytes)));
359 assertTrue(Arrays.equals(array, Doubles.toArray(shorts)));
360 assertTrue(Arrays.equals(array, Doubles.toArray(ints)));
361 assertTrue(Arrays.equals(array, Doubles.toArray(floats)));
362 assertTrue(Arrays.equals(array, Doubles.toArray(longs)));
363 assertTrue(Arrays.equals(array, Doubles.toArray(doubles)));
364 }
365
366 public void testAsList_isAView() {
367 double[] array = {(double) 0, (double) 1};
368 List<Double> list = Doubles.asList(array);
369 list.set(0, (double) 2);
370 assertTrue(Arrays.equals(new double[] {(double) 2, (double) 1}, array));
371 array[1] = (double) 3;
372 assertThat(list).has().exactly((double) 2, (double) 3).inOrder();
373 }
374
375 public void testAsList_toArray_roundTrip() {
376 double[] array = { (double) 0, (double) 1, (double) 2 };
377 List<Double> list = Doubles.asList(array);
378 double[] newArray = Doubles.toArray(list);
379
380
381 list.set(0, (double) 4);
382 assertTrue(Arrays.equals(
383 new double[] { (double) 0, (double) 1, (double) 2 }, newArray));
384 newArray[1] = (double) 5;
385 assertEquals((double) 1, (double) list.get(1));
386 }
387
388
389 public void testAsList_subList_toArray_roundTrip() {
390 double[] array = { (double) 0, (double) 1, (double) 2, (double) 3 };
391 List<Double> list = Doubles.asList(array);
392 assertTrue(Arrays.equals(new double[] { (double) 1, (double) 2 },
393 Doubles.toArray(list.subList(1, 3))));
394 assertTrue(Arrays.equals(new double[] {},
395 Doubles.toArray(list.subList(2, 2))));
396 }
397
398 public void testAsListEmpty() {
399 assertSame(Collections.emptyList(), Doubles.asList(EMPTY));
400 }
401
402
403
404
405
406 private static Double referenceTryParse(String input) {
407 if (input.trim().length() < input.length()) {
408 return null;
409 }
410 try {
411 return Double.valueOf(input);
412 } catch (NumberFormatException e) {
413 return null;
414 }
415 }
416
417 @GwtIncompatible("Doubles.tryParse")
418 private static void checkTryParse(String input) {
419 Double expected = referenceTryParse(input);
420 assertEquals(expected, Doubles.tryParse(input));
421 assertEquals(expected != null,
422 Doubles.FLOATING_POINT_PATTERN.matcher(input).matches());
423 }
424
425 @GwtIncompatible("Doubles.tryParse")
426 private static void checkTryParse(double expected, String input) {
427 assertEquals(Double.valueOf(expected), Doubles.tryParse(input));
428 assertTrue(Doubles.FLOATING_POINT_PATTERN.matcher(input).matches());
429 }
430
431 @GwtIncompatible("Doubles.tryParse")
432 public void testTryParseHex() {
433 for (String signChar : ImmutableList.of("", "+", "-")) {
434 for (String hexPrefix : ImmutableList.of("0x", "0X")) {
435 for (String iPart : ImmutableList.of("", "0", "1", "F", "f", "c4", "CE")) {
436 for (String fPart : ImmutableList.of("", ".", ".F", ".52", ".a")) {
437 for (String expMarker : ImmutableList.of("p", "P")) {
438 for (String exponent : ImmutableList.of("0", "-5", "+20", "52")) {
439 for (String typePart : ImmutableList.of("", "D", "F", "d", "f")) {
440 checkTryParse(
441 signChar + hexPrefix + iPart + fPart + expMarker + exponent + typePart);
442 }
443 }
444 }
445 }
446 }
447 }
448 }
449 }
450
451 @GwtIncompatible("Doubles.tryParse")
452 public void testTryParseAllCodePoints() {
453
454 char[] tmp = new char[2];
455 for (int i = Character.MIN_CODE_POINT; i < Character.MAX_CODE_POINT; i++) {
456 Character.toChars(i, tmp, 0);
457 checkTryParse(String.copyValueOf(tmp, 0, Character.charCount(i)));
458 }
459 }
460
461 @GwtIncompatible("Doubles.tryParse")
462 public void testTryParseOfToStringIsOriginal() {
463 for (double d : NUMBERS) {
464 checkTryParse(d, Double.toString(d));
465 }
466 }
467
468 @GwtIncompatible("Doubles.tryParse")
469 public void testTryParseOfToHexStringIsOriginal() {
470 for (double d : NUMBERS) {
471 checkTryParse(d, Double.toHexString(d));
472 }
473 }
474
475 @GwtIncompatible("Doubles.tryParse")
476 public void testTryParseNaN() {
477 checkTryParse("NaN");
478 checkTryParse("+NaN");
479 checkTryParse("-NaN");
480 }
481
482 @GwtIncompatible("Doubles.tryParse")
483 public void testTryParseInfinity() {
484 checkTryParse(Double.POSITIVE_INFINITY, "Infinity");
485 checkTryParse(Double.POSITIVE_INFINITY, "+Infinity");
486 checkTryParse(Double.NEGATIVE_INFINITY, "-Infinity");
487 }
488
489 private static final String[] BAD_TRY_PARSE_INPUTS =
490 { "", "+-", "+-0", " 5", "32 ", " 55 ", "infinity", "POSITIVE_INFINITY", "0x9A", "0x9A.bE-5",
491 ".", ".e5", "NaNd", "InfinityF" };
492
493 @GwtIncompatible("Doubles.tryParse")
494 public void testTryParseFailures() {
495 for (String badInput : BAD_TRY_PARSE_INPUTS) {
496 assertFalse(Doubles.FLOATING_POINT_PATTERN.matcher(badInput).matches());
497 assertEquals(referenceTryParse(badInput), Doubles.tryParse(badInput));
498 assertNull(Doubles.tryParse(badInput));
499 }
500 }
501
502 @GwtIncompatible("NullPointerTester")
503 public void testNulls() {
504 new NullPointerTester().testAllPublicStaticMethods(Doubles.class);
505 }
506
507 public void testStringConverter_convert() {
508 Converter<String, Double> converter = Doubles.stringConverter();
509 assertEquals((Double) 1.0, converter.convert("1.0"));
510 assertEquals((Double) 0.0, converter.convert("0.0"));
511 assertEquals((Double) (-1.0), converter.convert("-1.0"));
512 assertEquals((Double) 1.0, converter.convert("1"));
513 assertEquals((Double) 0.0, converter.convert("0"));
514 assertEquals((Double) (-1.0), converter.convert("-1"));
515 assertEquals((Double) 1e6, converter.convert("1e6"));
516 assertEquals((Double) 1e-6, converter.convert("1e-6"));
517 }
518
519 public void testStringConverter_convertError() {
520 try {
521 Doubles.stringConverter().convert("notanumber");
522 fail();
523 } catch (NumberFormatException expected) {
524 }
525 }
526
527 public void testStringConverter_nullConversions() {
528 assertNull(Doubles.stringConverter().convert(null));
529 assertNull(Doubles.stringConverter().reverse().convert(null));
530 }
531
532 @GwtIncompatible("Double.toString returns different value in GWT.")
533 public void testStringConverter_reverse() {
534 Converter<String, Double> converter = Doubles.stringConverter();
535 assertEquals("1.0", converter.reverse().convert(1.0));
536 assertEquals("0.0", converter.reverse().convert(0.0));
537 assertEquals("-1.0", converter.reverse().convert(-1.0));
538 assertEquals("1000000.0", converter.reverse().convert(1e6));
539 assertEquals("1.0E-6", converter.reverse().convert(1e-6));
540 }
541
542 @GwtIncompatible("NullPointerTester")
543 public void testStringConverter_nullPointerTester() throws Exception {
544 NullPointerTester tester = new NullPointerTester();
545 tester.testAllPublicInstanceMethods(Doubles.stringConverter());
546 }
547 }